package finance

import org.apache.commons.math.optimization.fitting.PolynomialFitter
import org.apache.commons.math.optimization.general.LevenbergMarquardtOptimizer
import org.apache.commons.math.analysis.polynomials.PolynomialFunction
import org.apache.commons.math.stat.regression.SimpleRegression
import org.apache.commons.math.distribution.TDistributionImpl

class PolynomialFitService {

    static transactional = true

    def fit(degree, vals) {
        PolynomialFitter fitter = new PolynomialFitter(degree, new LevenbergMarquardtOptimizer())
        
        for(i in 0 ..<vals.size() ) 
            fitter.addObservedPoint( i + 1, vals[i], i + 1)
        
        
        PolynomialFunction fitted = fitter.fit()
        
        def regression = new SimpleRegression(new TDistributionImpl(degree))
        
        for(i in 0 ..<vals.size() ) 
            regression.addData(vals[i], fitted.value(vals[i]))
        
        
        return [coefficients : fitted.getCoefficients(), rsquare: regression.getRSquare()]
    }
    
    def fit(degree, vals, vals2) {
        PolynomialFitter fitter = new PolynomialFitter(degree as int, new LevenbergMarquardtOptimizer())
        
        for(i in 0 ..<vals.size() )
            fitter.addObservedPoint( 1, vals[i], vals2[i])
        
        
        return fitter.fit()
    }
    
    def eval(vals, poly) {
       def map = [:]
       
       vals.each {
           map[ it ] = poly.value( it ) 
       }
       
       return map
    }
}
